home *** CD-ROM | disk | FTP | other *** search
Oberon Text | 1995-08-03 | 12.0 KB | 347 lines | [TEXT/.Ob4] |
- Syntax10.Scn.Fnt
- StampElems
- Alloc
- 3 Aug 95
- Syntax10b.Scn.Fnt
- Syntax10m.Scn.Fnt
- Syntax10i.Scn.Fnt
- MarkElems
- Alloc
- MODULE LinkElems; (** HM
- IMPORT
- Files, Fonts, Display, Input, Viewers, Texts, TextFrames, MenuViewers, TextPrinter, Oberon, PopupElems, MarkElems, FoldElems;
- CONST
- left =2; middle = 1; right = 0;
- pixel = LONG(10000);
- stdMenu = "System.Close System.Copy System.Grow Edit.Search Edit.Replace Edit.Store ";
- Elem* = POINTER TO ElemDesc;
- ElemDesc* = RECORD (Texts.ElemDesc)
- file*: ARRAY 32 OF CHAR;
- key*: LONGINT
- END;
- FollowMsg* = RECORD (Texts.ElemMsg) f*: Display.Frame END;
- Menu* = POINTER TO MenuDesc;
- MenuDesc* = RECORD (PopupElems.ElemDesc)
- END;
- Frame = POINTER TO FrameDesc;
- FrameDesc = RECORD (TextFrames.FrameDesc)
- e: Elem
- END;
- searchKey: LONGINT; (*key of mark element searched in FollowLink; used in Check*)
- hint: TextFrames.Frame; (*suggests frame to be used for links emanating from a link menu*)
- icon, invIcon: Display.Pattern; (* x = 0, y = 3, w = 9, h = 8 *)
- w: Texts.Writer;
- PROCEDURE^ New* (file: ARRAY OF CHAR; key: LONGINT): Elem;
- PROCEDURE
- GetSelection (VAR f: TextFrames.Frame);
- (* return frame f with the latest text selection*)
- VAR v: Viewers.Viewer; f0: Display.Frame; time: LONGINT; x: INTEGER;
- BEGIN
- x := 0; time := -1; f := NIL;
- WHILE x < Display.Width DO
- v := Viewers.This(x, 0);
- WHILE v.state > 1 DO
- f0 := v.dsc;
- WHILE f0 # NIL DO
- WITH f0: TextFrames.Frame DO
- IF f0.hasSel & (f0.time > time) THEN f := f0; time := f.time END
- ELSE
- END;
- f0 := f0.next
- END;
- v := Viewers.Next(v)
- END;
- x := x + v.W
- END GetSelection;
- PROCEDURE
- GetFileName (t: Texts.Text; VAR name: ARRAY OF CHAR);
- (* return the name of the viewer which contains text t*)
- VAR v, V: Viewers.Viewer; f: Display.Frame; s: Texts.Scanner; x: INTEGER;
- BEGIN
- V := NIL; x := 0;
- WHILE x < Display.Width DO
- v := Viewers.This(x, 0);
- WHILE v.state > 1 DO
- f := v.dsc;
- WHILE f # NIL DO
- IF (f IS TextFrames.Frame) & (f(TextFrames.Frame).text = t) THEN V := v END;
- f := f.next
- END;
- v := Viewers.Next(v)
- END;
- x := x + v.W
- END;
- IF V # NIL THEN
- Texts.OpenScanner(s, V.dsc(TextFrames.Frame).text, 0); Texts.Scan(s);
- IF s.class IN {Texts.Name, Texts.String} THEN COPY(s.s, name) ELSE name[0] := 0X END
- END GetFileName;
- PROCEDURE
- GetFrame (name: ARRAY OF CHAR; VAR f: TextFrames.Frame);
- VAR x: INTEGER; v: Viewers.Viewer; s: Texts.Scanner;
- BEGIN
- IF hint # NIL THEN f := hint
- ELSE
- x := 0; f := NIL;
- WHILE x < Display.Width DO
- v := Viewers.This(x, 0);
- WHILE v.state > 1 DO
- IF (v.dsc # NIL) & (v.dsc IS TextFrames.Frame) THEN
- Texts.OpenScanner(s, v.dsc(TextFrames.Frame).text, 0); Texts.Scan(s);
- IF s.s = name THEN f := v.dsc.next(TextFrames.Frame); RETURN END
- END;
- v := Viewers.Next(v)
- END;
- x := x + v.W
- END
- END GetFrame;
- PROCEDURE
- GetDsr (f: Display.Frame; pos: LONGINT; fnt: Fonts.Font; VAR dsr: INTEGER);
- VAR p: TextFrames.Parc; beg: LONGINT;
- BEGIN
- IF f = NIL THEN
- IF fnt = NIL THEN dsr := 0 ELSE dsr := - fnt.minY END
- ELSE
- TextFrames.ParcBefore(f(TextFrames.Frame).text, pos, p, beg);
- dsr := SHORT(p.dsr DIV TextFrames.Unit)
- END GetDsr;
- PROCEDURE
- CollectMarks (pop: Menu; f0: Display.Frame);
- (* Fill popup menu with all mark elements in f0.next.text*)
- VAR r: Texts.Reader; s: Texts.Scanner; ch: CHAR; f: TextFrames.Frame; mark: MarkElems.Elem; link: Elem; n: INTEGER;
- file: ARRAY 32 OF CHAR;
- BEGIN
- pop.menu := TextFrames.Text("");
- IF (f0.next = NIL) OR ~ (f0.next IS TextFrames.Frame) THEN
- Texts.WriteString(w, "link menu not in menu bar of a text viewer"); Texts.WriteLn(w); Texts.WriteLn(w)
- ELSE
- f := f0.next(TextFrames.Frame); hint := f; GetFileName(f.text, file); n := 0;
- Texts.OpenReader(r, f.text, 0); Texts.ReadElem(r);
- WHILE ~ r.eot DO
- IF r.elem IS MarkElems.Elem THEN
- mark := r.elem(MarkElems.Elem);
- link := New(file, mark.key);
- Texts.WriteElem(w, link); Texts.Write(w, " ");
- Texts.OpenScanner(s, f.text, Texts.Pos(r)); Texts.Scan(s);
- WHILE ~s.eot & (s.class # Texts.Name) DO Texts.Scan(s) END;
- IF ~s.eot THEN Texts.WriteString(w, s.s); Texts.WriteLn(w); INC(n)
- END
- END;
- Texts.ReadElem(r)
- END;
- IF n = 0 THEN Texts.WriteString(w, "no marks"); Texts.WriteLn(w) END;
- IF n <= 1 THEN Texts.WriteLn(w) END;
- END;
- Texts.Append(pop.menu, w.buf); PopupElems.MeasureMenu(pop)
- END CollectMarks;
- PROCEDURE
- ShowPos (f: TextFrames.Frame; pos: LONGINT);
- VAR beg, end, delta: LONGINT;
- BEGIN delta := 200;
- LOOP beg := f.org; end := TextFrames.Pos(f, f.X + f.W, f.Y);
- IF (beg <= pos) & (pos < end) OR (delta = 0) THEN EXIT END;
- TextFrames.Show(f, pos - delta); delta := delta DIV 2
- END;
- TextFrames.SetSelection(f, pos, pos + 1)
- END ShowPos;
- PROCEDURE
- Check (e: Texts.Elem): BOOLEAN;
- BEGIN RETURN (e IS MarkElems.Elem) & (e(MarkElems.Elem).key = searchKey)
- END Check;
- PROCEDURE
- FollowLink* (file: ARRAY OF CHAR; key: LONGINT; backF: Display.Frame; backE: Texts.Elem);
- VAR v: Viewers.Viewer; menu: TextFrames.Frame; x, y: INTEGER; t: Texts.Text; buf: Texts.Buffer;
- mark: Texts.Elem; f: TextFrames.Frame;
- BEGIN
- GetFrame(file, f);
- IF f = NIL THEN
- f := TextFrames.NewText(TextFrames.Text(file), 0);
- Oberon.AllocateUserViewer(Oberon.Mouse.X, x, y);
- IF Files.Old("Edit.Menu.Text") = NIL THEN menu := TextFrames.NewMenu(file, stdMenu)
- ELSE menu := TextFrames.NewMenu(file, "");
- NEW(t); Texts.Open(t, "Edit.Menu.Text");
- NEW(buf); Texts.OpenBuf(buf); Texts.Save(t, 0, t.len, buf); Texts.Append(menu.text, buf)
- END;
- v := MenuViewers.New(menu, f, TextFrames.menuH, x, y)
- END;
- searchKey := key;
- FoldElems.FindElem(f.text, 0, Check, mark);
- IF mark # NIL THEN
- ShowPos(f, Texts.ElemPos(mark));
- IF backF # NIL THEN MarkElems.backF := backF(TextFrames.Frame) ELSE MarkElems.backF := NIL END;
- MarkElems.backE := backE
- END FollowLink;
- PROCEDURE
- Edit (e: Elem);
- VAR t: Texts.Text; v: MenuViewers.Viewer; f: Frame; x, y: INTEGER;
- BEGIN
- t := TextFrames.Text("");
- Texts.WriteString(w, e.file); Texts.Write(w, " "); Texts.WriteInt(w, e.key, 0);
- Texts.Append(t, w.buf);
- NEW(f); f.e := e; TextFrames.Open(f, t, 0);
- Oberon.AllocateSystemViewer(0, x, y);
- v := MenuViewers.New(
- TextFrames.NewMenu("LinkElem", "System.Close LinkElems.Update "),
- f, TextFrames.menuH, x, y)
- END Edit;
- PROCEDURE
- Handle* (e: Texts.Elem; VAR m: Texts.ElemMsg);
- VAR e1: Elem; x, y, dsr, i: INTEGER; keys: SET; ch: CHAR; follow: FollowMsg;
- BEGIN
- WITH e: Elem DO
- WITH m: Texts.FileMsg DO
- IF m.id = Texts.load THEN
- i := 0; REPEAT Files.Read(m.r, ch); e.file[i] := ch; INC(i) UNTIL ch = 0X;
- Files.ReadLInt(m.r, e.key)
- ELSE (*Texts.store*)
- i := 0; REPEAT ch := e.file[i]; Files.Write(m.r, ch); INC(i) UNTIL ch = 0X;
- Files.WriteLInt(m.r, e.key)
- END
- | m: Texts.CopyMsg DO
- IF m.e = NIL THEN NEW(e1); m.e := e1 ELSE e1 := m.e(Elem) END;
- Texts.CopyElem(e, e1); COPY(e.file, e1.file); e1.key := e.key
- | m: Texts.IdentifyMsg DO
- m.mod := "LinkElems"; m.proc := "Alloc"
- | m: TextFrames.DisplayMsg DO
- IF ~m.prepare THEN
- GetDsr(m.frame, m.pos, m.fnt, dsr);
- Display.CopyPattern(Display.white, icon, m.X0, m.Y0+dsr, Display.paint)
- END
- | m: TextPrinter.PrintMsg DO
- IF m.prepare THEN e.W := 1 ELSE e.W := 10 * pixel END
- | m: TextFrames.TrackMsg DO
- IF middle IN m.keys THEN
- IF m.frame # NIL THEN
- GetDsr(m.frame, m.pos, m.fnt, dsr);
- Display.CopyPattern(Display.white, icon, m.X0, m.Y0+dsr, Display.invert);
- Display.CopyPattern(Display.white, invIcon, m.X0, m.Y0+dsr, Display.invert);
- REPEAT Input.Mouse(keys, x, y); m.keys := m.keys + keys;
- Oberon.DrawCursor(Oberon.Mouse, Oberon.Arrow, x, y)
- UNTIL keys = {};
- Display.CopyPattern(Display.white, invIcon, m.X0, m.Y0+dsr, Display.invert);
- Display.CopyPattern(Display.white, icon, m.X0, m.Y0+dsr, Display.invert)
- END;
- IF m.keys = {middle} THEN follow.f := m.frame; e.handle(e, follow)
- ELSIF m.keys = {middle, right} THEN Edit(e)
- END
- END
- | m: FollowMsg DO
- FollowLink(e.file, e.key, m.f, e)
- ELSE
- END
- END Handle;
- PROCEDURE
- HandleMenu* (e: Texts.Elem; VAR m: Texts.ElemMsg);
- VAR e1: Menu;
- BEGIN
- WITH e: Menu DO
- WITH
- m: Texts.IdentifyMsg DO
- m.mod := "LinkElems"; m.proc := "AllocMenu"
- | m: Texts.CopyMsg DO
- NEW(e1); m.e := e1; PopupElems.Handle(e, m)
- | m: TextFrames.DisplayMsg DO
- IF m.prepare THEN
- e.W := 13 * pixel; e.H := LONG(TextFrames.menuH-1) * pixel;
- ELSE e.name := ""; PopupElems.Handle(e, m);
- Display.CopyPattern(Display.white, icon, m.X0+2, m.Y0+3, Display.paint)
- END
- | m: TextFrames.TrackMsg DO
- IF middle IN m.keys THEN
- CollectMarks(e, m.frame); PopupElems.Handle(e, m); hint := NIL
- END
- ELSE PopupElems.Handle(e, m)
- END
- END HandleMenu;
- PROCEDURE
- Alloc*;
- VAR e: Elem;
- BEGIN
- NEW(e); e.handle := Handle; Texts.new := e
- END Alloc;
- PROCEDURE
- AllocMenu*;
- VAR e: Menu;
- BEGIN
- NEW(e); e.handle := HandleMenu; Texts.new := e
- END AllocMenu;
- PROCEDURE
- New* (file: ARRAY OF CHAR; key: LONGINT): Elem;
- VAR e: Elem;
- BEGIN
- NEW(e); e.W := 10 * pixel; e.H := 11 * pixel; e.handle := Handle; COPY(file, e.file); e.key := key;
- RETURN e
- END New;
- PROCEDURE
- Insert*;
- VAR link: Elem; mark: MarkElems.Elem; fromT, toT: Texts.Text; toPos, end, time: LONGINT;
- r: Texts.Reader; ch: CHAR; m: TextFrames.InsertElemMsg; f: TextFrames.Frame;
- BEGIN
- f := Oberon.FocusViewer.dsc(TextFrames.Frame);
- IF f.hasCar THEN fromT := f.text ELSE fromT := f.next(TextFrames.Frame).text END;
- Oberon.GetSelection(toT, toPos, end, time);
- IF time >= 0 THEN
- link := New("", 0); GetFileName(toT, link.file);
- Texts.OpenReader(r, toT, toPos); Texts.Read(r, ch);
- m.e := link; Viewers.Broadcast(m);
- IF (ch = Texts.ElemChar) & (r.elem IS MarkElems.Elem) THEN
- link.key := r.elem(MarkElems.Elem).key
- ELSE
- IF (fromT = toT) & (Texts.ElemPos(link) <= toPos) THEN INC(toPos) END;
- mark := MarkElems.New(); link.key := mark.key;
- Texts.WriteElem(w, mark); Texts.Insert(toT, toPos, w.buf)
- END
- END Insert;
- PROCEDURE
- InsertMenu*;
- VAR e: Menu; insert: TextFrames.InsertElemMsg;
- BEGIN
- NEW(e); e.handle := HandleMenu; e.name := ""; e.menu := TextFrames.Text(""); e.small := TRUE;
- PopupElems.MeasureMenu(e);
- insert.e := e; Viewers.Broadcast(insert)
- END InsertMenu;
- PROCEDURE
- Update*;
- VAR f: Frame; t: Texts.Text; s: Texts.Scanner; r: Texts.Reader; ch: CHAR;
- BEGIN
- IF (Oberon.Par.frame = Oberon.Par.vwr.dsc) & (Oberon.Par.frame.next IS Frame) THEN
- f := Oberon.Par.frame.next(Frame);
- Texts.OpenScanner(s, f.text, 0); Texts.Scan(s);
- IF s.class = Texts.Name THEN
- COPY(s.s, f.e.file); Texts.Scan(s);
- IF s.class = Texts.Int THEN
- f.e.key := s.i;
- t := Oberon.Par.frame(TextFrames.Frame).text;
- Texts.OpenReader(r, t, t.len-1); Texts.Read(r, ch);
- IF ch = "!" THEN Texts.Delete(t, t.len-1, t.len) END
- END
- END
- END Update;
- PROCEDURE
- InitIcon;
- VAR line: ARRAY 9 OF SET;
- BEGIN
- line[8] := {4};
- line[7] := {3, 5};
- line[6] := {2, 6};
- line[5] := {1..3, 5..7};
- line[4] := {3, 5};
- line[3] := {3, 5};
- line[2] := {3, 5};
- line[1] := {3..5};
- icon := Display.NewPattern(line, 9, 8);
- line[8] := {4};
- line[7] := {3..5};
- line[6] := {2..6};
- line[5] := {1..7};
- line[4] := {3..5};
- line[3] := {3..5};
- line[2] := {3..5};
- line[1] := {3..5};
- invIcon := Display.NewPattern(line, 9, 8)
- END InitIcon;
- BEGIN
- Texts.OpenWriter(w);
- InitIcon;
- hint := NIL
- END LinkElems.
-